package com.tanhua.back.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tanhua.back.entity.AnalysisByDay;
import com.tanhua.back.entity.AreaEnum;
import com.tanhua.back.mapper.AnalysisByDayMapper;
import com.tanhua.back.mapper.UserInfoMapper;
import com.tanhua.back.service.AnalysisByDayService;
import com.tanhua.back.vo.AnalysisByDayVo;
import com.tanhua.back.vo.DistributionVo;
import com.tanhua.back.vo.YearItem;
import com.tanhua.back.vo.YearItemVo;
import com.tanhua.model.domain.mongodb.Video;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

@Service
@Slf4j
public class AnalysisByDayServiceImpl extends ServiceImpl<AnalysisByDayMapper, AnalysisByDay> implements AnalysisByDayService {

    @Autowired
    private AnalysisByDayMapper analysisByDayMapper;
    @Autowired
    private UserInfoMapper userInfoMapper;

    /**
     * 概要统计信息
     *
     * @return
     */
    @Override
    public AnalysisByDayVo summary() {
        AnalysisByDayVo vo = new AnalysisByDayVo();
        //1.获取全部用户
        Long cumulativeUsers = analysisByDayMapper.cumulativeUsers();
        vo.setCumulativeUsers(cumulativeUsers);
        //2.过去30天活跃用户
        //当前时间
        String dateStr = "2020-09-09";
        DateTime date = DateUtil.parse(dateStr);
        //2.过去30天活跃用户
        Long activePassMonth = this.queryActiveUserCount(date, -30);
        vo.setActivePassMonth(activePassMonth);
        //3.过去7天活跃用户
        Long activePassWeek = this.queryActiveUserCount(date, -7);
        vo.setActivePassWeek(activePassWeek);
        //4.今日新增注册用户
        Long newUsersToday = this.querySingleUserCount(date, "num_registered");
        vo.setNewUsersToday(newUsersToday);
        //5.今日新增用户涨跌率
        //(今日新增人数-昨日新增人数)/昨日新增人数
        DateTime proDate = DateUtil.offsetDay(date, -1);
        //昨日新增
        Long newUsersYesterdday = this.querySingleUserCount(proDate, "num_registered");
        BigDecimal newUsersTodayRate = computeRate(newUsersToday, newUsersYesterdday);
        vo.setNewUsersTodayRate(newUsersTodayRate);
        //6.今日登录次数
        Long loginTimesToday = this.querySingleUserCount(date, "num_login");
        vo.setLoginTimesToday(loginTimesToday);
        //7.今日登录次数涨跌率
        //(今日新增人数-昨日新增人数)/昨日新增人数
        Long loginTimesYesterdday = this.querySingleUserCount(proDate, "num_login");
        BigDecimal loginTimesTodayRate = computeRate(loginTimesToday, loginTimesYesterdday);
        vo.setLoginTimesTodayRate(loginTimesTodayRate);
        //8.今日活跃用户
        Long activeUsersToday = this.querySingleUserCount(date, "num_active");
        vo.setActiveUsersToday(activeUsersToday);
        //11.昨日活跃用户
        Long activeUsersYesterday = this.querySingleUserCount(proDate, "num_active");
        vo.setActiveUsersYesterday(activeUsersYesterday);
        //9.今日活跃用户涨跌率
        BigDecimal activeUsersTodayRate = computeRate(activeUsersToday, activeUsersYesterday);
        vo.setActiveUsersTodayRate(activeUsersTodayRate);
        //10.过去7天平均日使用时长
        //12.昨日活跃用户涨跌率
        //后天
        DateTime proToYesterdayDate = DateUtil.offsetDay(date, -2);
        Long activeUsersToYesterday = this.querySingleUserCount(proToYesterdayDate, "num_active");
        BigDecimal activeUsersToYesterdayRate = computeRate(activeUsersYesterday, activeUsersToYesterday);
        vo.setActiveUsersYesterdayRate(activeUsersToYesterdayRate);
        vo.setUseTimePassWeek(10000L);
        vo.setLorem8("quis");
        vo.setUte6(-94534143.48756799);
        return vo;
    }

    /**
     * 新增,活跃,留存
     *
     * @param sd
     * @param ed
     * @param type
     * @return
     */
    @Override
    public YearItemVo usersInfo(String sd, String ed, Integer type) {
        /*
//        Long start = Convert.toLong(sd);
//        Long end = Convert.toLong(ed);
//        Date startDate = new Date(start);
//        // String startFormatDate = DateUtil.formatDate(startDate);
//        Date endDate = new Date(end);
//        //String endFormatDate = DateUtil.formatDate(endDate);
*/

        sd = "2018-01-01";
        ed = "2019-12-31";
        //查询这段时间的对象数据
        switch (type) {
            case 101:
                return getYearItemVo(sd, ed, "num_registered");
            case 102:
                //活跃用户
                return getYearItemVo(sd, ed, "num_active");
            case 103:
                //次日留存率
                return getYearItemVo(sd, ed, "num_retention1d");
        }
        return new YearItemVo();
    }

    //根据时间段获取
    private YearItemVo getYearItemVo(String sd, String ed, String cloume) {
        YearItemVo vo = new YearItemVo();
        List<YearItem> thisYear = this.getYearAmount(sd, cloume);
        //利用结束时间获取今年的第一天
        Date ends = DateUtil.parse(ed);
        //获取今年的第一天
        DateTime dateTime = DateUtil.beginOfYear(ends);
        String end = DateUtil.formatDate(dateTime);
        List<YearItem> lastYear = this.getYearAmount(end, cloume);
        vo.setThisYear(thisYear);
        vo.setLastYear(lastYear);
        return vo;
    }

    /**
     * 注册用户分布，行业top、年龄、性别、地区
     *
     * @param sd
     * @param ed
     * @return
     */

    @Override
    public DistributionVo distribution(String sd, String ed) {
        Long start = Convert.toLong(sd);
        Long end = Convert.toLong(ed);
        Date startDate = new Date(start);
        String startFormatDate = DateUtil.formatDate(startDate);
        Date endDate = new Date(end);
        String endFormatDate = DateUtil.formatDate(endDate);
        DistributionVo vo = new DistributionVo();
        //1.行业分布TOP10
        List<YearItem> industrys = this.industryDistribution();
        vo.setIndustryDistribution(industrys);

        //2.年龄分布
        List<YearItem> ages = this.ageDistribution();
        vo.setAgeDistribution(ages);

        //3.性别分布
        List<YearItem> genders = this.genderDistribution();
        vo.setGenderDistribution(genders);

        //4.地区分布
        List<YearItem> areas = this.areaDistribution();
        vo.setLocalTotal(areas);

        //5.地区合计
        List<YearItem> localTotals = this.localTotalDistribution();
        vo.setLocalDistribution(localTotals);

        //将返回值转化为json对象
        Object toJSON = JSON.toJSON(vo);
        log.info("数据:{}", toJSON);
        return vo;
    }

    /**
     * 地区---各个城市的统计
     *
     * @return
     */
    private List<YearItem> localTotalDistribution() {
        //1.通过模糊查询得到各个省会的名称
        //1.得到每个用户的城市名称
        List<String> areaNames = userInfoMapper.getArea("city");
        //2.对每一个字段进行切割并得到相应的大区名称
        Map<String, Integer> map = new HashMap<>();
        for (String areaName : areaNames) {
            String[] split = areaName.split("-");
            if (!map.containsKey(split[0])) {
                map.put(split[0], 1);
            } else {
                map.put(split[0], map.get(split[0]) + 1);
            }
        }
        //3.将map集合转换为list进行封装
        List<YearItem> localDistribution = new ArrayList<>();
        map.forEach((key, value) -> {
            YearItem yearItem = new YearItem();
            if (key.contains("省")) {
                String k = key.substring(0, key.indexOf("省"));
                yearItem.setTitle(k);
            } else {
                String k = key.substring(0, 2);
                yearItem.setTitle(k);
            }
            yearItem.setAmount(value);
            localDistribution.add(yearItem);
        });
        return localDistribution;
    }

    /**
     * 各个大区分布
     *
     * @return
     */
    private List<YearItem> areaDistribution() {
        //1.得到每个用户的城市名称
        List<String> areaNames = userInfoMapper.getArea("city");
        //2.对每一个字段进行切割并得到相应的大区名称
        Map<String, Integer> map = new HashMap<>();
        for (String areaName : areaNames) {
            String[] split = areaName.split("-");
            String area = AreaEnum.getAreaByProvince(split[0]);
            if (!map.containsKey(area)) {
                map.put(area, 1);
            } else {
                map.put(area, map.get(area) + 1);
            }
        }
        //3.将map集合转换为list进行封装
        List<YearItem> localDistribution = new ArrayList<>();
        map.forEach((key, value) -> {
            YearItem yearItem = new YearItem(key, value);
            localDistribution.add(yearItem);
        });
        return localDistribution;
    }

    /**
     * 行业分布
     */
    private List<YearItem> industryDistribution() {
        //1.分组得到各个行业的集合
        List<String> professions = userInfoMapper.getClunme("profession");
        //2.根据各个行业的集合去进行查找各个行业在数据库中的个数
        List<YearItem> yearItems = new ArrayList<>();
        for (String profession : professions) {
            if (profession != null) {
                int count = userInfoMapper.getClunmeCount("profession", profession);
                YearItem yearItem = new YearItem();
                yearItem.setTitle(profession);
                yearItem.setAmount(count);
                yearItems.add(yearItem);
            }
        }
        //3.对数据进行封装并返回
        return yearItems;
    }

    /**
     * 年龄分布
     *
     * @return
     */
    private List<YearItem> ageDistribution() {
        List<YearItem> yearItemList = new ArrayList<>();
        int amount1 = userInfoMapper.ageDistribution(0, 17, "age");
        yearItemList.add(new YearItem("0到17岁", amount1));
        int amount2 = userInfoMapper.ageDistribution(18, 22, "age");
        yearItemList.add(new YearItem("18到22岁", amount2));
        int amount3 = userInfoMapper.ageDistribution(24, 30, "age");
        yearItemList.add(new YearItem("24到30岁", amount3));
        int amount4 = userInfoMapper.ageDistribution(41, 50, "age");
        yearItemList.add(new YearItem("41到50岁", amount4));
        int amount5 = userInfoMapper.ageDistribution(50, 100, "age");
        yearItemList.add(new YearItem("50以上", amount5));
        return yearItemList;
    }

    /**
     * 性别分布
     *
     * @return
     */
    private List<YearItem> genderDistribution() {
        //1.得到性别
        List<String> genders = userInfoMapper.getClunme("gender");
        List<YearItem> yearItems = new ArrayList<>();
        for (String gender : genders) {
            if (gender != null) {
                int count = userInfoMapper.getClunmeCount("gender", gender);
                YearItem yearItem = new YearItem();
                if (StringUtils.equalsIgnoreCase(gender, "man")) {
                    yearItem.setTitle("男性用户");
                } else {
                    yearItem.setTitle("女性用户");
                }
                yearItem.setAmount(count);
                yearItems.add(yearItem);
            }
        }
        return yearItems;
    }

    /**
     * 单日统计方法
     *
     * @param dateTime
     * @return
     */
    private Long querySingleUserCount(DateTime dateTime, String clume) {
        String proDay = DateUtil.formatDate(dateTime);
        return analysisByDayMapper.getCout(proDay, clume);
    }

    /**
     * 过去n天活跃用户
     *
     * @return
     */
    private Long queryActiveUserCount(DateTime dateTime, int i) {
        String today = DateUtil.formatDate(dateTime);
        DateTime proDate = DateUtil.offsetDay(dateTime, i);
        String proDay = DateUtil.formatDate(proDate);
        return analysisByDayMapper.queryActiveUserCount("num_active", today, proDay);
    }

    /**
     * 计算各个率
     *
     * @param current
     * @param last
     * @return
     */
    private static BigDecimal computeRate(Long current, Long last) {
        BigDecimal result;
        if (last == 0) {
            // 当上一期计数为零时，此时环比增长为倍数增长
            result = new BigDecimal((current - last));
        } else {
            result = BigDecimal.valueOf((current - last)).divide(BigDecimal.valueOf(last), 2, BigDecimal.ROUND_HALF_DOWN);
        }
        return result;
    }

    //今天的个月份的统计数据
    private List<YearItem> getYearAmount(String startFormatDate, String cloume) {
        List<YearItem> yearItems = new ArrayList<>();
        //获取当前时间
        Date start = DateUtil.parse(startFormatDate);
        for (int i = 1; i < 13; i++) {
            DateTime begin = DateUtil.beginOfMonth(start);
            String beginD = DateUtil.formatDate(begin);
            DateTime iend = DateUtil.endOfMonth(start);
            String endD = DateUtil.formatDate(iend);
            int amount = userInfoMapper.getAmountByColume(beginD, endD, cloume);
            YearItem yearItem = new YearItem(i + "月", amount);
            yearItems.add(yearItem);
            //利用本月的结束时间进行偏移1天就可以进行下月的第一天,并可以算出下个月的最后一天
            start = DateUtil.offsetDay(iend, 1);//下月的第一天
        }
        return yearItems;
    }
}
